home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1996 April / MacFormat CD Edition MF36 (April 1996).iso / Floppy / CopyBeep / CopyBeep Source / copyBeep.p next >
Text File  |  1992-08-16  |  5KB  |  177 lines

  1. { CopyBeep ©1992 Gregory M. Robbins 3/92 }
  2. { 3/92 v 1.0 }
  3. { 5/92 v 1.1 plays snd resource }
  4.  
  5. UNIT CopyBeep;
  6. INTERFACE
  7.  
  8. USES
  9.     Processes, Traps, Sound;
  10. PROCEDURE main;
  11.  
  12. IMPLEMENTATION
  13.  
  14. PROCEDURE CloseWindowPatch (theWindowPtr: WindowPeek);
  15. forward;
  16.  
  17. PROCEDURE ShowWindowPatch (theWindowPtr: WindowPeek);
  18. forward;
  19.  
  20. PROCEDURE storage;
  21. forward;
  22.  
  23. FUNCTION Gestalt (selector: OSType; VAR response: LongInt): OSErr;
  24. { this gestalt interface takes far fewer bytes than the standard glue }
  25. INLINE
  26.     $4E56, $0000, { LINK A6,#0 ; make a cushy stack frame }
  27.     $202E, $0008, { MOVE.L $8(A6),D0 ; get the selector }
  28.     $A1AD, { _Gestalt }
  29.     $226E, $0004, { MOVEA.L $4(A6),A1 ; stuff the response }
  30.     $2288, { MOVE.L A0,(A1) }
  31.     $3D40, $000C, { MOVE.W D0,$C(A6) ; put the error code on the stack }
  32.     $4E5E, { UNLK A6 ; back to our previously scheduled scope }
  33.     $508F; { ADDQ.L #8,A7 ; trash them parameters }
  34.  
  35. PROCEDURE main;
  36.     VAR
  37.         toolScratchPtr: ^Ptr;
  38.         myHandle: Handle;
  39.         tempAddr: Ptr;
  40.         storagePtr: ^Ptr;
  41.  
  42.         delayPtr: IntegerPtr;
  43.         delayResHandle: Handle;
  44.  
  45.         sndHandle: Handle;
  46.         sndHandlePtr: LongIntPtr;
  47.  
  48.         gestaltResponse: LongInt;
  49.         retCode: OSErr;
  50.  
  51.     BEGIN
  52.  
  53.         { Think Pascal points toolScratch to the start of the block }
  54.         toolScratchPtr := Pointer($9CE);
  55.         myHandle := RecoverHandle(toolScratchPtr^);
  56.  
  57.         { check if Gestalt is implemented }
  58.         IF NGetTrapAddress(_GestaltDispatch, OSTrap) = NGetTrapAddress(_Unimplemented, ToolTrap) THEN
  59.             Exit(main)
  60.         ELSE
  61.             BEGIN
  62.                 { if there's no process manager cause the system version is less than 7.0, bail }
  63.                 retCode := Gestalt(gestaltSystemVersion, gestaltResponse);
  64.                 IF (retCode <> noErr) OR (gestaltResponse < $0700) THEN
  65.                     Exit(main)
  66.             END;
  67.  
  68.         { make the init float free; it must have been loaded in the System heap and locked }
  69.         DetachResource(myHandle);
  70.  
  71.         { patch ShowWindow, $A915 }
  72.         tempAddr := Pointer(NGetTrapAddress(_ShowWindow, ToolTrap));
  73.         storagePtr := @storage;
  74.         storagePtr^ := tempAddr;
  75.         SetToolTrapAddress(LongInt(@ShowWindowPatch), _ShowWindow);
  76.  
  77.         { patch CloseWindow, $A92D }
  78.         tempAddr := Ptr(NGetTrapAddress(_CloseWindow, ToolTrap));
  79.         storagePtr := Pointer(LongInt(@storage) + 4);
  80.         storagePtr^ := tempAddr;
  81.         SetTrapAddress(LongInt(@CloseWindowPatch), _CloseWindow);
  82.  
  83.         { get delay value }
  84.         delayPtr := IntegerPtr(LongInt(@storage) + 12);
  85.         delayResHandle := Get1IndResource('DLAY', 1);
  86.         IF delayResHandle <> NIL THEN
  87.             BEGIN
  88.                 delayPtr^ := IntegerPtr(delayResHandle^)^;
  89.                 ReleaseResource(delayResHandle);
  90.             END
  91.         ELSE
  92.             delayPtr^ := 15;
  93.  
  94.         { get sound resource }
  95.         sndHandlePtr := LongIntPtr(LongInt(@storage) + 14);
  96.         sndHandle := Get1IndResource('snd ', 1);
  97.         sndHandlePtr^ := LongInt(sndHandle);
  98.         IF sndHandle <> NIL THEN
  99.             DetachResource(sndHandle);
  100.  
  101.     END;
  102.  
  103. FUNCTION FinderIsCurrentProcess: Boolean;
  104.     VAR
  105.         thePSN: ProcessSerialNumber;
  106.         thePIR: ProcessInfoRec;
  107.     BEGIN
  108.         FinderIsCurrentProcess := FALSE;
  109.         WITH thePIR DO
  110.             BEGIN
  111.                 processInfoLength := SizeOf(ProcessInfoRec);
  112.                 processName := NIL;
  113.                 processAppSpec := NIL
  114.             END;
  115.         IF GetCurrentProcess(thePSN) = noErr THEN
  116.             IF GetProcessInformation(thePSN, thePIR) = noErr THEN
  117.                 IF thePIR.processSignature = 'MACS' THEN
  118.                     FinderIsCurrentProcess := TRUE;
  119.     END;
  120.  
  121. PROCEDURE ShowWindowPatch (theWindowPtr: WindowPeek);
  122.  
  123.     PROCEDURE ExitPatch (PP: longint);
  124.     INLINE
  125.         $205F,        { MOVEA.L (A7)+,A0 }
  126.         $265F,        { MOVEA.L (A7)+,A3 ; compiled code preserved A3 }
  127.         $4E5E,        { UNLK A6 }
  128.         $4ED0;        { JMP (A0) }
  129.     VAR
  130.         tempLongIntPtr: LongIntPtr;
  131.     BEGIN
  132.         IF theWindowPtr^.windowKind = $14 THEN
  133.             IF theWindowPtr^.goAwayFlag = FALSE THEN
  134.                 IF FinderIsCurrentProcess THEN
  135.                     BEGIN { store current tick count }
  136.                         tempLongIntPtr := LongIntPtr(LongInt(@storage) + 8);
  137.                         tempLongIntPtr^ := TickCount;
  138.                     END;
  139.         ExitPatch(LongIntPtr(@storage)^);
  140.     END;
  141.  
  142. PROCEDURE CloseWindowPatch (theWindowPtr: WindowPeek);
  143.  
  144.     PROCEDURE ExitPatch (PP: longint);
  145.     INLINE
  146.         $205F,        { MOVEA.L (A7)+,A0  }
  147.         $4E5E,        { UNLK A6 }
  148.         $4ED0;        { JMP (A0) }
  149.  
  150.     VAR
  151.         retCode: OSErr;
  152.     BEGIN
  153.         IF theWindowPtr^.windowKind = $14 THEN
  154.             IF theWindowPtr^.goAwayFlag = FALSE THEN
  155.                 IF FinderIsCurrentProcess THEN
  156.                     IF LongIntPtr(LongInt(@storage) + 8)^ + 60 * IntegerPtr(LongInt(@storage) + 12)^ < TickCount THEN { been more than 15 secs }
  157.                         IF LongIntPtr(LongInt(@storage) + 8)^ + 216000 > TickCount THEN { forget it after an hour }
  158.                             BEGIN
  159.                                 IF LongIntPtr(LongInt(@storage) + 14)^ <> LongInt(NIL) THEN { play the sound }
  160.                                     retCode := SndPlay(NIL, Handle(LongIntPtr(LongInt(@storage) + 14)^), false)
  161.                                 ELSE { no sound resource, so just beep }
  162.                                     SysBeep(20);
  163.                             END;
  164.         ExitPatch(LongIntPtr(LongInt(@storage) + 4)^)
  165.     END;
  166.  
  167.  
  168. PROCEDURE storage;
  169. { storage: ShowWindow addr; +4: CloseWindow addr; +8: tickcount at ShowWindow break; }
  170. { +12: min delay in seconds; +14: sndHandle }
  171.     PROCEDURE nops;
  172.     INLINE
  173.         $4E71, $4E71, $4E71, $4E71, $4E71, $4E71;
  174.     BEGIN
  175.         nops
  176.     END;
  177. END.